#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <wchar.h>

#include "../src/matches.h"

int main()
{
	/* expected return value */
	begend exp;
	/* actual return value */
	begend act;

	rxAnaRess *rress;

#define FIRST(TEXT,REGEX,BEGIN,END)	\
	exp.begin = BEGIN; exp.end = END;	\
	rress = rxCompile( REGEX, RF_EXTENDED, RCO_DEFAULT );	\
	act = firstMatch( TEXT, rress );	\
	assert( (exp.begin == act.begin && exp.end == act.end) );

#define NEXT(BEGIN,END)	\
	exp.begin = BEGIN; exp.end = END;	\
	act = nextDisjunctMatch( rress );	\
	assert( (exp.begin == act.begin && exp.end == act.end) );

#define NONEXT	\
	act = nextDisjunctMatch( rress );	\
	assert( act.begin == invBegend.begin && act.end == invBegend.end );

	wprintf( L"Tests for literal regexp...\t" );

	FIRST( L"a", L"a", 0, 1 )
	NONEXT
	freeRress( rress );

// 	EXPECT( L"a", L"(a)", 0, 1,  );
// 	EXPECT( L"a", L"(((((a)))))", 0, 1,  );
// 	EXPECT( L"a", L"(((((A)))))", 0, 1, ! );
// 	EXPECT( L"ab", L"ab", 0, 2,  );
// 	EXPECT( L"ab", L"a(b)", 0, 2,  );
// 	EXPECT( L"abcdef", L"a(b)c((d).)f", 0, 6,  );
// 	EXPECT( L"abCdef ", L"a(b)c((d).)f", 0, 6, ! );
// 	EXPECT( L"ba", L"a", 1, 2,  );
// 	EXPECT( L"baobabaababa", L"bababa", 3, 9, ! );
// 	EXPECT( L"baobabaababa", L"aababa", 6, 12,  );
// 	EXPECT( L"ab", L"(a)(b)", 0, 2,  );
// 	EXPECT( L"baobabaababa", L"a(((a)(ba))ba)", 6, 12,  );
// 	EXPECT( L"ab", L".", 1, 2, ! );
// 	EXPECT( L"abcdefghikjlmnop", L"................", 0, 16,  );
// 	EXPECT( L"abcdefghikjlmnop", L".................", 0, 16, ! );
// 	EXPECT( L"abcdefghikjlmnop", L"...............", 1, 16, ! );
	wprintf( L"\tOK\n" );

	wprintf( L"Tests for non-nested repetitions...\t" );

	FIRST( L"aa", L"a*", 0, 2 )
	NEXT( 2, 2 )
	NONEXT
	freeRress( rress );


// 
// 	EXPECT( L"barbara", L"c*(a|r){2}b*a", 1, 5,  );
// 	assert( matches( L"baa", L"a*" ) );
// 	assert( matches( L"", L"a*" ) );
// 	assert( matches( L"b", L"a*" ) );
// 
// 	assert( matches( L"baa", L"aa*" ) );
// 	assert( ! matches( L"", L"aa*" ) );
// 	assert( ! matches( L"b", L"aa*" ) );
// 
// 	assert( matches( L"baa", L"(aa){1,}" ) );
// 	assert( ! matches( L"", L"(aa){1,}" ) );
// 	assert( ! matches( L"b", L"(aa){1,}" ) );
// 
// 	assert( matches( L"baa", L"(aa|b){2,2}" ) );
// 	assert( ! matches( L"baba", L"(aa|b){2,2}" ) );
// 	assert( matches( L"baaba", L"(aa|b){2,2}" ) );
// 	assert( matches( L"baaba", L"(a(a)|b){2,2}" ) );
// 	assert( matches( L"baaba", L"b(a(a)|b){2,2}" ) );
// 	assert( ! matches( L"baaa", L"b(a(a)|b){2,2}" ) );
// 

	FIRST( L"", L"(a*(b*))c*(d*(e*)*)", 0, 0 )
	NONEXT
	freeRress( rress );

// 	assert( ! matches( L"", L"(a*(b*))xc*(d*(e*)*)" ) );
// 	assert( matches( L"x", L"(a*(b*))xc*(d*(e*)*)" ) );
// 
// 	assert( matches( L"bacabacababaabca", L"((((a(a)|b){2,2})))" ) );
// 	assert( ! matches( L"bacabacababaabca", L"((((a(a)|b){4,})))" ) );
// 
// 	assert( matches( L"abbc", L"ab{1,2}c" ) );
// 	assert( ! matches( L"abbbc", L"ab{1,2}c" ) );
// 
// 	assert( matches( L"ab", L"a{1}b{1}" ) );

	FIRST( L"abbbc", L"(ab*c|b)", 0, 5 )
	NONEXT
	freeRress( rress );

	FIRST( L"bababbabaaabbbaa", L"a{1,2}a*b{1}", 1, 3 )
	NEXT( 3, 5 )
	NEXT( 6, 8 )
	NEXT( 8, 12 )
	NONEXT
	freeRress( rress );

// 	assert( matches( L"abcca", L"bc{2,2}" ) );
// 	assert( matches( L"XXXaabcccdXXaabcccddX", L"a{2}bc{3}d{1,2}d" ) );
// 	assert( ! matches( L"XXXaabcccdXXaabcccdX", L"a{2}bc{3}d{1,2}d" ) );
// 
// 	assert( matches( L"abbcccd", L"ab{1,2}c{0,3}d" ) );
// 	assert( ! matches( L"abbbccccd", L"ab{1,2}c{0,3}d" ) );

	wprintf( L"\tOK\n" );


	wprintf( L"Tests for nested repetitions...\t" );

// 	assert( matches( L"aa", L"(a{1}){2,4}" ) );
// 	assert( matches( L"abcabcd", L"(a{1,2}bc){2,4}" ) );
// 	assert( matches( L"abcbcd", L"(a*bc){2,4}" ) );
// 	assert( ! matches( L"abcbad", L"(a*bc){2,4}" ) );
// 	assert( matches( L"bbc", L"(bc*){2,4}" ) );
// 	assert( matches( L"bccbc", L"(bc*){2,4}" ) );
// 	assert( matches( L"abcaccbc", L"(b(a|c)*){2,4}" ) );
// 	assert( ! matches( L"abcdccbc", L"(b(a|c)*){2,4}" ) );
// 	assert( matches( L"acbbcd", L"(bc*){2,4}" ) );
// 	assert( matches( L"baabcd", L"(a*b){2,4}" ) );
// 	assert( matches( L"aabbcd", L"(a*b){2,4}" ) );

	FIRST( L"abaaabaabbaabd", L"(a*b){2,4}", 0, 10 )
	NONEXT
	freeRress( rress );

// 	assert( matches( L"abcaaabcd", L"(aa?a?bc){2,4}" ) );
// 	assert( ! matches( L"abcabaabcd", L"(a*bc){2,4}" ) );
// 	assert( matches( L"bb", L"(a*b){1,2}(a*b){1,2}" ) );
// 	assert( matches( L"bbbb", L"(a*b){2,4}(a*b){2,4}" ) );
// 	assert( matches( L"babbab", L"(a*b){2,4}(a*b){2,4}" ) );
// 	assert( matches( L"efgdaddabcaaabcd", L"g(d(a|d)){1,2}" ) );
// 	assert( matches( L"efgdaddabcaaabcd", L"g(d(a|d)){1,2}(a*bc){2,4}" ) );
// 	assert( matches( L"efgdaddaabcaaabcd", L"g(d(a|d)){1,2}(aaa*bc){2,4}" ) );
// 	assert( ! matches( L"efgdadaddabcaaabcd", L"g(d(a|d)){1,2}(a*bc){2,4}" ) );

	wprintf( L"\tOK\n" );


	wprintf( L"Tests for anchors...\t" );

// 	assert( matches( L"a", L"^a$" ) );
// 	assert( matches( L"", L"^$" ) );
// 	assert( ! matches( L"ba", L"^a" ) );
// 
// 	assert( matches( L"ba", L"a$$$" ) );
// 	assert( ! matches( L"ba", L"^$^ba$$$" ) );
// 	assert( matches( L"", L"^$^$$$" ) );
// 
// 	assert( matches( L"aab", L"(aa|b)$" ) );
// 	assert( matches( L"aab", L"(aaa|b$)" ) );
// 	assert( ! matches( L"aab", L"(aa$|^b)" ) );
// 	assert( matches( L"aab", L"(a?^a|$b)" ) );

	FIRST( L"aab", L"(a?^aa?|b$)", 0, 2 )
	NEXT( 2, 3 )
	freeRress( rress );

	FIRST( L"aab", L"(a?^aa?|b$)", 0, 2 )
	NEXT( 2, 3 )
	NONEXT
	freeRress( rress );

	FIRST( L"aab", L"(a?^aa?|b$){1,2}", 0, 3 )
	NONEXT
	freeRress( rress );


	wprintf( L"\tOK\n" );

// 	wprintf( L"Tests for \"&\"...\t" );
// 
// 	assert( matches( L"a", L"a&a" ) );
// 	assert( matches( L"a", L".*&a" ) );
// 	assert( ! matches( L"ab", L"a&b" ) );
// 
// 	assert( matches( L"a", L"a&a&a" ) );
// 	assert( matches( L"a", L"(a&a)" ) );
// 	assert( matches( L"a", L"a&(a)&a" ) );
// 	assert( matches( L"a", L"a&(a&a)&a" ) );
// 	assert( ! matches( L"a", L".*&a&(b)&a" ) );
// 	assert( matches( L"a", L".*&a&(b|(a&.))&a" ) );
// 
// 	assert( matches( L"abc", L"^&.(b|c){2,}" ) );
// 	assert( ! matches( L"abc", L"^&(b|c){2,}" ) );
// 	assert( ! matches( L"abc", L"^&.(b|c){2,}&b" ) );
// 
// 	assert( matches( L"abcdfoobarefg", L"f(o*&oo(b|c)ar)&......efg$" ) );
// 	assert( ! matches( L"abcdfoobarefg", L"f(o*&oo(b|c)ar)&.....efg$" ) );
// 
// 	assert( matches( L"aa", L"(a{1}){2,4}&a" ) );
// 	assert( matches( L"aa", L"a&(a{1}){2,4}&a" ) );
// 	assert( matches( L"ggabcaaabcd", L"a&(aa?a?bc){2,4}" ) );
// 	assert( matches( L"bb", L"(a*b){2,4}&(a*b){2,4}" ) );
// 	assert( matches( L"bab", L"b&(a*b){2,4}" ) );
// 	assert( matches( L"bab", L"(a*b){2,4}&b" ) );
// 	assert( ! matches( L"bab", L"(a*b){2,4}&a" ) );
// 	assert( matches( L"bb", L"(a*b){2,4}&(a*b){2,4}" ) );
// 	assert( matches( L"bab", L"(a*b){2,4}&(a*b){2,4}" ) );
// 	assert( matches( L"abaab", L"(a*b){2,4}&(a*b){2,4}" ) );
// 	assert( matches( L"ab", L"a*&a" ) );
// 	assert( matches( L"ab", L"a*&b" ) );
// 	assert( matches( L"ab", L"a*b&ab" ) );
// 	assert( matches( L"abab", L"(a*b){2,4}&(ab){2,4}" ) );
// 	assert( matches( L"ggabcaaabcd", L"(a*bc){2,4}&(aa?a?bc){2,4}" ) );
// 	assert( matches( L"ggabcaaabcd", L"(a*bc){2,4}&(ax*a?a?bc){2,4}" ) );
// 	assert( ! matches( L"ggabcaaabcd", L"(a*bc){2,4}&(gax*a?a?bc){2,4}" ) );
// 	assert( ! matches( L"ggabcaaabcd", L"(a*bc){2,4}&g(ax*a?a?bc){2,4}" ) );
// 	assert( ! matches( L"ggabcaaabcd", L"gg(a*bc){2,4}&g(ax*a?a?bc){2,4}" ) );
// 
// 	wprintf( L"\tOK\n" );


	wprintf( L"Tests for nextDisjunctMatch() finished.\n" );
	return 0;
}

